#include "Socket.hpp"

Socket::Socket() : socket_()
{
}

Socket::~Socket()
{
}

bool Socket::connect(const std::string &hostname, const char *port)
{
  struct addrinfo *result;
  struct addrinfo *p;
  struct addrinfo hints;
  int error;
  int optval;

  hints.ai_family = PF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  error = ::getaddrinfo(hostname.c_str(), port, NULL, &result);
  if (error != 0)
    {   
      std::cerr << "error in getaddrinfo: " << ::gai_strerror(error) << std::endl;
      ::freeaddrinfo(result);
      return false;
    }
  for (p = result; p != NULL; p = p->ai_next) 
    {
      if ((this->socket_ = ::socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 
	continue;
      optval = 1;
      if (::setsockopt(this->socket_, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) 
	{
	  std::cerr << "Can't set sockopt " << ::strerror(errno) << std::endl;
	  continue;
	}
      if (::connect(this->socket_, p->ai_addr, p->ai_addrlen) == -1) 
	{
	  ::close(this->socket_);
	  continue;
	}
      break;
    }
  ::freeaddrinfo(result);
  if (p == NULL) 
    {
      std::cerr << "failed to connect" << std::endl;
      return false;
    }
  return true;
}

bool Socket::send(const std::string &msg)
{
  return this->send(msg.c_str(), msg.length());
}

bool Socket::send(const char *msg, int size)
{
  int rv;
  int nb_written;

  for (nb_written = 0; nb_written < size;)
    {
      rv = ::write(this->socket_, msg + nb_written, size - nb_written);
      if (rv == -1)
	{
	  std::cerr << strerror(errno) << std::endl;
	  return false;
	}
      nb_written += rv;
    }
  return true;
}

void Socket::close()
{
  ::close(this->socket_);
}
